import { defineComponent, reactive, ref, watchEffect } from 'vue';
import { createUseStyles } from 'vue-jss';

import SchemaForm from '../lib/SchemaForm.tsx';

import MonacoEditor from './components/MonacoEditor.tsx';
import demos from './demos';

// TODO: 在lib中export
type Schema = any;
type UISchema = any;

function toJson(schema: any) {
  return JSON.stringify(schema, null, 2);
}

const useStyles = createUseStyles({
  container: {
    display: 'flex',
    flexDirection: 'column',
    height: '100%',
    width: '1200px',
    margin: '0 auto',
  },
  menu: {
    marginBottom: 20,
  },
  code: {
    width: 700,
    flexShrink: 0,
  },
  codePanel: {
    minHeight: 400,
    marginBottom: 20,
  },
  uiAndValue: {
    'display': 'flex',
    'justifyContent': 'space-between',
    '& > *': {
      width: '46%',
    },
  },
  content: {
    display: 'flex',
  },
  form: {
    padding: '0 20px',
    flexGrow: 1,
  },
  menuButton: {
    'appearance': 'none',
    'borderWidth': 0,
    'backgroundColor': 'transparent',
    'cursor': 'pointer',
    'display': 'inline-block',
    'padding': 15,
    'borderRadius': 5,
    '&:hover': {
      background: '#efefef',
    },
  },
  menuSelected: {
    'background': '#337ab7',
    'color': '#fff',
    '&:hover': {
      background: '#337ab7',
    },
  },
});

export default defineComponent({
  setup() {
    const selectedRef = ref(0);

    const demo: {
      schema: Schema | null;
      data: any;
      uiSchema: UISchema | null;
      schemaCode: string;
      dataCode: string;
      uiSchemaCode: string;
    } = reactive({
      schema: null,
      data: {},
      uiSchema: {},
      schemaCode: '',
      dataCode: '',
      uiSchemaCode: '',
    });

    watchEffect(() => {
      const index = selectedRef.value;
      const d = demos[index];
      demo.schema = d.schema;
      demo.data = d.default;
      demo.uiSchema = d.uiSchema;
      demo.schemaCode = toJson(d.schema);
      demo.dataCode = toJson(d.default);
      demo.uiSchemaCode = toJson(d.uiSchema);
    });

    const handleChange = (v: any) => {
      console.log('🚀 line:103 ----- v', v);
      demo.data = v;
      demo.dataCode = toJson(v);
    };

    function handleCodeChange(
      filed: 'schema' | 'data' | 'uiSchema',
      value: string,
    ) {
      try {
        const json = JSON.parse(value);
        demo[filed] = json
        ;(demo as any)[`${filed}Code`] = value;
      } catch (err) {
        console.log('🚀 line:125 ----- err', err);
      }
    }

    const handleSchemaChange = (v: string) => handleCodeChange('schema', v);
    const handleDataChange = (v: string) => handleCodeChange('data', v);
    const handleUISchemaChange = (v: string) => handleCodeChange('uiSchema', v);

    const classesRef = useStyles();

    return () => {
      const classes = classesRef.value;
      const selected = selectedRef.value;

      return (
        <div class={classes.container}>
          <div class={classes.menu}>
            <h1>Vue3 JsonSchema Form</h1>

            <div>
              {demos.map((demo, index) => (
                <button
                  class={{
                    [classes.menuButton]: true,
                    [classes.menuSelected]: index === selected,
                  }}
                  onClick={() => (selectedRef.value = index)}
                >
                  {demo.name}
                </button>
              ))}
            </div>
          </div>

          <div class={classes.content}>
            <div class={classes.code}>
              <MonacoEditor
                class={classes.codePanel}
                code={demo.schemaCode}
                title='Schema'
                onChange={handleSchemaChange}
              />

              <div class={classes.uiAndValue}>
                <MonacoEditor
                  class={classes.codePanel}
                  code={demo.uiSchemaCode}
                  title='UISchema'
                  onChange={handleUISchemaChange}
                />

                <MonacoEditor
                  class={classes.codePanel}
                  code={demo.dataCode}
                  title='Value'
                  onChange={handleDataChange}
                />
              </div>
            </div>

            <div class={classes.form}>
              <SchemaForm schema={demo.schema} value={demo.data} onChange={handleChange} />
            </div>
          </div>
        </div>
      );
    };
  },
});
